<?php

declare (strict_types=1);
/**
 * @copyright 深圳市易果网络科技有限公司
 * @version 1.0.0
 * @link https://dayiguo.com
 */

namespace App\Kernel\Traits;

use Hyperf\Database\Model\Model;
use Hyperf\Database\Model\Builder;

/**
 * Trait
 *
 * @author 刘兴永(aile8880@qq.com)
 * @package App\Kernel\Traits
 */
trait DaoTrait
{
    use QueryTrait;

    /**
     * Get model.
     *
     * @return string
     */
    abstract public function model(): string;

    /**
     * make Model
     *
     * @return Builder|null
     */
    public function makeModel()
    {
        $model = make($this->model());

        return $model instanceof Model ? $model::query() : null;
    }

    /**
     * Get multiple pieces of data.
     *
     * @param array $map 查询条件
     * @param array $columns 查询列
     * @param string|null $order 排序
     * @param int|null $paginate 分页
     * @return mixed
     */
    public function multiple(array $map = [], array $columns = ['*'], string $order = null, int $paginate = null)
    {
        $model = self::makeModel();

        if (!empty($map)) {
            $model = $model->where(function($query) use ($map) { return self::genQuery($query, $map); });
        }

        if (null !== $order) {
            $model = $model->orderByRaw($order);
        }

        // 如果使用了分页，需要强制使用主键索引，避免分页数据错乱
        if ($paginate !== null) {
            $model = $model->orderBy('id');
        }

        $model = $model->select($columns);

        return $paginate > 0 ? $model->paginate($paginate) : $model->get();
    }

    /**+
     *
     * Query a single piece of data.
     *
     * @param array|int $map 查询条件或主键
     * @param array $columns 查询列
     * @param string|null $order 排序语句
     * @param string|null $error 异常终止提示
     * @return mixed
     */
    public function find($map = [], array $columns = ['*'], string $order = null, string $error = null)
    {
        $model = self::makeModel();

        if (is_int($map)) {
            $model = $model->where('id', (int)$map);
        }
        if (!empty($map) && is_array($map)) {
            $model = $model->where(function($query) use ($map) { return self::genQuery($query, $map); });
        }

        if (null !== $order) {
            $model = $model->orderByRaw($order);
        }

        $first = $model->select($columns)->first();

        if (!$first && null !== $error && method_exists($this, 'error')) {
            $this->error($error);
        }

        return $first;
    }

    /**
     * Create data.
     *
     * @param array $data
     * @return mixed
     */
    public function create(array $data)
    {
        return self::makeModel()->create($data);
    }

    /**
     * According to the update condition data.
     *
     * @param int|array $map 更新条件，可以直接为主键，也可以为数组
     * @param array $data 更新数据
     * @return bool|int
     */
    public function update($map, array $data)
    {
        $model = self::makeModel();

        if (is_array($map) && !empty($map)) {
            return $model->where(function($query) use ($map) { return self::genQuery($query, $map); })->update($data);
        } else if (is_int($map)) {
            return $model->where('id', (int)$map)->update($data);
        } else {
            return false;
        }
    }

    /**
     * Delete data in accordance with conditions.
     *
     * @param int|array $map 删除条件，可以直接为主键，也可以为数组
     * @return bool|int|mixed
     */
    public function delete($map)
    {
        $model = self::makeModel();

        if (is_array($map) && !empty($map)) {
            return $model->where(function($query) use ($map) { return self::genQuery($query, $map); })->delete();
        } else if (is_int($map)) {
            return $model->where('id', (int)$map)->delete();
        } else {
            return false;
        }
    }
}